﻿//------------------------------------------------------------------------------
// The contents of this file are subject to the Microsoft Public License (Ms-PL)
// You may obtain a copy of the License at http://psadmin.codeplex.com/license. 
// 
// Software distributed under the License is distributed on an "AS IS" basis, 
// WITHOUT WARRANTY OF ANY KIND, either express or implied. 
// See the License for the specific language governing rights and limitations 
// under the License.
// 
// The initial developer is Ben Foster (ben.foster@retroviz.com)
// Copyright (c) Retroviz Limited (http://www.retroviz.com).
// All Rights Reserved.
//------------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using PSAdmin.Core.Domain;
using PSAdmin.Core.Interfaces;
using NHibernate;
using NHibernate.Linq;
using NHibernate.Criterion;
using PSAdmin.Core;
using PSAdmin.Core.Security;

namespace PSAdmin.Data.Repositories
{
    public class PSScriptRepository : IPSScriptRepository
    {
        private ISession _session;
        
        public PSScriptRepository(ISession session) {
            _session = session;
        }
        
        public int Save(PSScript entity) {
            using (ITransaction txn = _session.BeginTransaction()) {
                _session.SaveOrUpdate(entity);
                txn.Commit();
            }
            return entity.Id;
        }

        public void Delete(PSScript entity) {
            using (var txn = _session.BeginTransaction()) {
                _session.Delete(entity);
                txn.Commit();
            }
        }

        public PSScript GetById(int id) {
            return _session.CreateCriteria<PSScript>()
                .Add(NHibernate.Criterion.Expression.Eq("Id", id))
                .SetFetchMode("Variables", FetchMode.Eager)
                .UniqueResult<PSScript>();
        }

        public ICollection<PSScript> GetAll() {
            return _session.CreateCriteria<PSScript>()
                .SetFetchMode("Variables", FetchMode.Eager)
                .SetFirstResult(5)
                .SetMaxResults(10)
                .List<PSScript>();
        }

        public PagedList<PSScript> GetPaged(int pageIndex, int pageSize) {
            var rowCount = _session.CreateCriteria<PSScript>()
                                .SetProjection(Projections.RowCount())
                                .FutureValue<Int32>();

            var results = _session.CreateCriteria<PSScript>()
                .SetFirstResult((pageIndex - 1) * pageSize)
                .SetMaxResults(pageSize)
                .Future<PSScript>()
                .ToList<PSScript>();

            return new PagedList<PSScript>(results, pageSize, pageSize, rowCount.Value);
        }

        public PagedList<PSScript> GetScriptsForUser(string username, int pageIndex, int pageSize) {
            // TODO - implement database paging with future row count
            var rolesForUser = DetachedCriteria.For<UserRole>()
                    .SetProjection(Projections.Property("Id"))
                    .CreateCriteria("Users")
                        .Add(Expression.Eq("Username", username.ToLower()));

            var scripts = _session.CreateCriteria<PSScript>()
                .CreateCriteria("Roles")
                    .Add(Subqueries.PropertyIn("Id", rolesForUser))
                .List<PSScript>();

            return new PagedList<PSScript>(scripts.ToList(), pageIndex, pageSize, scripts.Count());
        }
    }
}
